package net.oschina.arvin.dbjava.model;

import net.oschina.arvin.dbjava.util.Utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 数据库表对应的列
 *
 * @author Arvin
 * @time 2017/9/28 10:46
 */
public class Column {

    /**
     * 所属schema
     */
    private String schema;

    /**
     * 所属表
     */
    private String tablename;

    /**
     * 列名
     */
    private String columnName;

    /**
     * 顺序，越小越前面
     */
    private int order;

    /**
     * 默认值
     */
    private String defaultValue;

    /**
     * 是否允许为空
     */
    private boolean allowNull;

    /**
     * 长度，number属性才需要设置
     */
    private Integer numericPrecision;

    /**
     * 精度，number 类型才有
     */
    private Integer numericScale;

    /**
     * 时间类型才有的属性
     */
    private Integer datetimePrecision;

    /**
     * 编码
     */
    private String encoding;

    /**
     * 数据类型
     */
    private String dataType;

    /**
     * 列类型 如 varchar(10)
     */
    private String columnType;

    /**
     * 列长度，通过 columnType进行计算
     */
    private Integer columnLen;

    /**
     * 精度，即多少位小数位
     */
    private Integer columnDecimal;

    /**
     * 无符号
     */
    private boolean unsigned;

    /**
     * 使用0填充
     */
    private boolean zerofill;

    /**
     * 列的KEY
     * 可能会有4种值，即'啥也没有','PRI','UNI','MUL'
     * 1. 如果Key是空的, 那么该列值的可以重复, 表示该列没有索引, 或者是一个非唯一的复合索引的非前导列
     * 2. 如果Key是PRI,  那么该列是主键的组成部分
     * 3. 如果Key是UNI,  那么该列是一个唯一值索引的第一列(前导列),并别不能含有空值(NULL)
     * 4. 如果Key是MUL,  那么该列的值可以重复, 该列是一个非唯一索引的前导列(第一列)或者是一个唯一性索引的组成部分但是可以含有空值NULL
     */
    private String columnKey;

    /**
     * 扩展属性， 如auto_increment, on update CURRENT_TIMESTAMP
     */
    private String extra;

    /**
     * 注释
     */
    private String comment;

    public String getSchema() {
        return schema;
    }

    public void setSchema(String schema) {
        this.schema = schema;
    }

    public String getTablename() {
        return tablename;
    }

    public void setTablename(String tablename) {
        this.tablename = tablename;
    }

    public String getColumnName() {
        return columnName;
    }

    public void setColumnName(String columnName) {
        this.columnName = columnName;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public String getDefaultValue() {
        return defaultValue;
    }

    public void setDefaultValue(String defaultValue) {
        this.defaultValue = defaultValue;
    }

    public boolean isAllowNull() {
        return allowNull;
    }

    public void setAllowNull(boolean allowNull) {
        this.allowNull = allowNull;
    }

    public Integer getNumericPrecision() {
        return numericPrecision;
    }

    public void setNumericPrecision(Integer numericPrecision) {
        this.numericPrecision = numericPrecision;
    }

    public Integer getNumericScale() {
        return numericScale;
    }

    public void setNumericScale(Integer numericScale) {
        this.numericScale = numericScale;
    }

    public Integer getDatetimePrecision() {
        return datetimePrecision;
    }

    public void setDatetimePrecision(Integer datetimePrecision) {
        this.datetimePrecision = datetimePrecision;
    }

    public String getEncoding() {
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public String getDataType() {
        return dataType;
    }

    public void setDataType(String dataType) {
        this.dataType = dataType;
    }

    public boolean isPrimaryKey() {
        return null != columnKey && columnKey.toUpperCase().contains("PRI");
    }

    public boolean isUniqueKey() {
        return null != columnKey && columnKey.toUpperCase().contains("UNI");
    }

    public String getColumnType() {
        return columnType;
    }

    public void setColumnType(String columnType) {
        this.columnType = columnType;
        // 计算长度
        if (Utils.isNotBlank(columnType)) {
            this.columnLen = calculateColumnLen(columnType);
            this.columnDecimal = calculateColumnDecimal(columnType);

            this.unsigned = columnType.toUpperCase().contains("unsigned");
            this.zerofill = columnType.toUpperCase().contains("zerofill");
        }
    }

    private Integer calculateColumnLen(String columnType) {
        String lenStr = columnType.replaceAll("^.*\\(([0-9]+).*$", "$1");
        Integer len = Utils.toInt(lenStr, null);
        if (null == len || len == 0) {
            len = this.numericPrecision;
        }
        return len;
    }

    private Integer calculateColumnDecimal(String columnType) {
        String str = columnType.replaceAll("^.*\\([0-9]+,([0-9]+).*$", "$1");
        Integer len = Utils.toInt(str, 0);
        if (null == len || len == 0) {
            len = this.numericScale;
        }
        return len;
    }

    public Integer getColumnLen() {
        return columnLen;
    }

    public Integer getColumnDecimal() {
        return columnDecimal;
    }

    public String getColumnKey() {
        return columnKey;
    }

    public boolean isUnsigned() {
        return unsigned;
    }

    public boolean isZerofill() {
        return zerofill;
    }

    public void setColumnKey(String columnKey) {
        this.columnKey = columnKey;
    }

    public String getExtra() {
        return extra;
    }

    public void setExtra(String extra) {
        this.extra = extra;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    /**
     * 获取枚举字符串列表
     */
    public List<String> getEnums() {
        if ("ENUM".equals(dataType.toUpperCase())) {
            String enumStr = this.columnType.replaceAll("^.*\\((.*)\\).*$", "$1").replaceAll("'", "");
            if (Utils.isNotBlank(enumStr)) {
                return Arrays.asList(enumStr.split(","));
            }
        }
        return null;
    }

    /**
     * 获取Set字符串列表
     */
    public List<String> getSets() {
        if ("SET".equals(dataType.toUpperCase())) {
            String setStr = this.columnType.replaceAll("^.*\\((.*)\\).*$", "$1").replaceAll("'", "");
            if (Utils.isNotBlank(setStr)) {
                return Arrays.asList(setStr.split(","));
            }
        }
        return null;
    }
}
